home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 2 / Mac Magazin and MacEasy Magazine CD - Issue 02.iso / Sharewarebibliothek / PowerMac / Rotate PPC ƒ / RotatePPC.c < prev    next >
Text File  |  1994-07-11  |  16KB  |  655 lines

  1. /* This program reads a set of 3D points from a file and
  2.    then displays them in a window where they can be rotated
  3.    around left-right and up-down.
  4.    
  5.    This version is only for the Power Macintosh.
  6.    It assumes System 7.1.2.
  7.    
  8.    It gives examples of using the required apple events,
  9.    file dropping, and reading c-style from an FSS record.
  10.    
  11.    The rotation code is from the NewSpaceShuttle source.
  12.    This code and program, as far as they are able to be,
  13.    are in the public domain.
  14.    
  15.    Craig Kloeden <craig@raru.adelaide.edu.au>
  16.    9 June 1994
  17. */
  18.  
  19. #include <QDOffscreen.h>
  20. #include <math.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <EPPC.h>
  24. #include <AppleEvents.h>
  25.  
  26. #define MaxPoints 2500
  27. #define PI    3.141592653589793
  28. #define PI2    6.283185307179586
  29.  
  30. void     main (void);
  31. void     init (void);
  32. void    HandleEvent (void);
  33. void    HandleMouseDown (EventRecord *theEvent);
  34. void    HandleMenu (long mSelect);
  35. void    finishup (void);
  36. void    mousepress (Point p);
  37. void     rotate (void);
  38. void     getuserfile (void);
  39. void    readfile (short refnum, long parid, Str63 name);
  40. void    installAEhandlers (void);
  41. void    DoHighLevelEvent (EventRecord *theEvent);
  42. pascal    OSErr    openAE (AppleEvent *theEvent, AppleEvent *reply, long refcon);
  43. pascal    OSErr    quitAE (AppleEvent *theEvent, AppleEvent *reply, long refcon);
  44. pascal    OSErr    printAE (AppleEvent *theEvent, AppleEvent *reply, long refcon);
  45. pascal    OSErr    startAE (AppleEvent *theEvent, AppleEvent *reply, long refcon);
  46. void    died (char desc[255], int code, int ref);
  47.  
  48. double        Xangle, Yangle, Zangle;
  49. double        aaa[MaxPoints][3];
  50. int            cc[MaxPoints];
  51. int            N;
  52. double        DD = 120;
  53. Boolean        done;
  54. Rect        frameRect, dragRect;
  55. CWindowPtr    thewindow;
  56. GWorldPtr    drawWorldP;
  57. PixMapHandle    thePixMapH, windowPixMapH;
  58. PixMapPtr    drawPixMapP, windowPixMapP;
  59. MenuHandle    applemenu, filemenu, editmenu, optionmenu;
  60. GWorldPtr    saveWorld;
  61. GDHandle    saveDevice;
  62. OSErr        err;
  63. RGBColor    black = {0,0,0}, white = {65535, 65535, 65535};
  64. RGBColor    red = {65535, 0, 0}, green = {0, 65535, 0}, blue = {0, 0, 65535};
  65.  
  66. //************************************************************************
  67.  
  68. void main (void)
  69. {
  70.     init ();
  71.     
  72.     done = false;
  73.     while (! done)
  74.         {
  75.         HandleEvent();
  76.         }
  77.     
  78.     finishup ();
  79. }
  80.  
  81. //************************************************************************
  82.  
  83. void init (void)
  84. {
  85.     EventRecord tempEvent;
  86.     
  87.     /* Initialize Managers */
  88.     InitGraf (&qd.thePort);
  89.     InitFonts ();
  90.     FlushEvents(everyEvent - osMask - diskMask, 0);
  91.     InitWindows ();
  92.     InitMenus ();
  93.     TEInit ();
  94.     InitDialogs (nil);
  95.     InitCursor ();
  96.     MaxApplZone();
  97.     MoreMasters();
  98.     
  99.     EventAvail(everyEvent, &tempEvent);
  100.     EventAvail(everyEvent, &tempEvent);
  101.     EventAvail(everyEvent, &tempEvent);
  102.     
  103.     /* set up menus */
  104.     applemenu = GetMenu(128);
  105.     if (applemenu == NULL) died ("Can't find Apple Menu Resource", 0, 001);
  106.     AddResMenu(applemenu, 'DRVR');
  107.     filemenu = GetMenu(129);
  108.     editmenu = GetMenu(130);
  109.     optionmenu = GetMenu(131);
  110.     InsertMenu(applemenu, 0);
  111.     InsertMenu(filemenu, 0);
  112.     InsertMenu(editmenu, 0);
  113.     InsertMenu(optionmenu, 0);
  114.     DrawMenuBar();
  115.     
  116.     dragRect = qd.screenBits.bounds;
  117.     SetRect (&frameRect, 0, 0, 400, 400);
  118.     
  119.     /* because this is PPC only we dont have to check for old
  120.        systems or the GWorld stuff :-)
  121.     */
  122.     
  123.     /* set up the main window */
  124.     thewindow = (CWindowPtr) GetNewCWindow (400, nil, (WindowPtr)-1L);
  125.     if (thewindow == NULL) died ("Can't get Window Resource", 0, 002);
  126.     SetPort ((WindowPtr)thewindow);
  127.     GetGWorld(&saveWorld, &saveDevice);
  128.     windowPixMapH = GetGWorldPixMap(saveWorld);
  129.     HLockHi((Handle)windowPixMapH);
  130.     LockPixels(windowPixMapH);
  131.     windowPixMapP = *thewindow->portPixMap;
  132.     
  133.     /* set up offscreen GWorld */
  134.     err = NewGWorld(&drawWorldP, 8, &frameRect, nil, nil, 0);
  135.     if (err) died ("Could not Create GWorld", err, 003);
  136.     thePixMapH = GetGWorldPixMap(drawWorldP);
  137.     HLockHi((Handle)thePixMapH);
  138.     LockPixels(thePixMapH);
  139.     drawPixMapP = *thePixMapH;
  140.     
  141.     /* clear the GWorld */
  142.     SetGWorld(drawWorldP, nil);
  143.     PaintRect(&frameRect);
  144.     SetGWorld(saveWorld, saveDevice);
  145.     
  146.     /* no points yet */
  147.     N = 0;
  148.     
  149.     installAEhandlers ();
  150. }
  151.  
  152. //************************************************************************
  153.  
  154. void HandleEvent(void)
  155. {
  156.     EventRecord    theEvent;
  157.  
  158.     HiliteMenu(0);
  159.     
  160.     if (WaitNextEvent (everyEvent, &theEvent, 40, NULL))
  161.       switch (theEvent.what)
  162.       {
  163.         case mouseDown:
  164.             HandleMouseDown(&theEvent);
  165.             break;
  166.             
  167.         case keyDown: 
  168.             if ((theEvent.modifiers & cmdKey) != 0)
  169.              {
  170.               HandleMenu(MenuKey((char) (theEvent.message & charCodeMask)));
  171.               }
  172.             break;
  173.             
  174.         case updateEvt:
  175.             BeginUpdate((WindowPtr)thewindow);
  176.             /* copy GWorld to screen window */
  177.             SetGWorld(saveWorld, saveDevice);
  178.             CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
  179.                 &frameRect, &frameRect, srcCopy, nil);
  180.             EndUpdate((WindowPtr)thewindow);
  181.            break;
  182.             
  183.         case activateEvt:
  184.             InvalRect(&thewindow->portRect);
  185.             break;
  186.             
  187.         case osEvt:
  188.             if (theEvent.message & 1) /* Resume Event */
  189.                 {
  190.                 InitCursor();
  191.                 }
  192.             else /* Suspend Event */
  193.                 {
  194.                 InitCursor();
  195.                 }
  196.             break;
  197.             
  198.         case kHighLevelEvent:
  199.             DoHighLevelEvent (&theEvent);
  200.             break;
  201.         }
  202. }
  203.  
  204. //************************************************************************
  205.  
  206. void HandleMouseDown (EventRecord *theEvent)
  207. {
  208.     WindowPtr    awindow;
  209.     int            windowCode = FindWindow (theEvent->where, &awindow);
  210.     
  211.     switch (windowCode)
  212.       {
  213.       case inSysWindow: 
  214.         SystemClick (theEvent, awindow);
  215.         break;
  216.         
  217.       case inMenuBar:
  218.         HandleMenu(MenuSelect(theEvent->where));
  219.         break;
  220.         
  221.       case inDrag:
  222.           if (awindow == (WindowPtr)thewindow)
  223.             DragWindow((WindowPtr)thewindow, theEvent->where, &dragRect);
  224.             break;
  225.             
  226.         case inContent:
  227.               if (awindow == (WindowPtr)thewindow)
  228.                 {
  229.                 if (awindow != FrontWindow())
  230.                     SelectWindow((WindowPtr)thewindow);
  231.                 else
  232.                     {
  233.                       GlobalToLocal(&theEvent->where);
  234.                       mousepress (theEvent->where);
  235.                     }
  236.                 }
  237.         break;
  238.           
  239.       case inGoAway:
  240.           if (awindow == (WindowPtr)thewindow && 
  241.               TrackGoAway((WindowPtr)thewindow, theEvent->where))
  242.               {
  243.             HideWindow ((WindowPtr)thewindow);
  244.             N = 0;
  245.             }
  246.         break;
  247.       }
  248. }
  249.  
  250. //************************************************************************
  251.  
  252. void HandleMenu (long mSelect)
  253. {
  254. int            menuID = HiWord(mSelect);
  255. int            menuItem = LoWord(mSelect);
  256. Str255        name;
  257. GrafPtr        savePort;
  258. unsigned    long        ticks;
  259.  
  260. switch (menuID)
  261.     {
  262.     case 128: /* apple menu */
  263.         if (menuItem == 1) /* About */
  264.             {
  265.             Alert(128,NULL);
  266.             break;
  267.             }
  268.         /* system apple menu item */
  269.         GetPort(&savePort);
  270.         GetItem(applemenu, menuItem, name);
  271.         OpenDeskAcc(name);
  272.         SetPort(savePort);
  273.         break;
  274.     
  275.     case 129: /* file menu */
  276.         switch (menuItem)
  277.             {
  278.             case 1: /* open */
  279.                 getuserfile();
  280.                 break;
  281.             case 3: /* quit */
  282.                 done = true;
  283.                 break;
  284.             }
  285.         break;
  286.     
  287.     case 131: /* option menu */
  288.         switch (menuItem)
  289.             {
  290.             case 1: /* perspective */
  291.                 if (DD == 120)
  292.                     {
  293.                     CheckItem (optionmenu, 1, FALSE);
  294.                     DD = 100000;
  295.                     }
  296.                 else
  297.                     {
  298.                     CheckItem (optionmenu, 1, TRUE);
  299.                     DD = 120;
  300.                     }
  301.                 SetGWorld(drawWorldP, nil);
  302.                 PaintRect(&frameRect);
  303.                 rotate ();
  304.                 SetGWorld(saveWorld, saveDevice);
  305.                 CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
  306.                     &frameRect, &frameRect, srcCopy, nil);
  307.                 break;
  308.             case 3: /* rotate slow*/
  309.                 while (! Button())
  310.                     {
  311.                     ticks = TickCount();
  312.                     Yangle++;
  313.                     SetGWorld(drawWorldP, nil);
  314.                     PaintRect(&frameRect);
  315.                     rotate ();
  316.                     SetGWorld(saveWorld, saveDevice);
  317.                     while (TickCount() < ticks + 1) {}
  318.                     CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
  319.                         &frameRect, &frameRect, srcCopy, nil);
  320.                     }
  321.                 break;
  322.             case 4: /* rotate fast*/
  323.                 while (! Button())
  324.                     {
  325.                     ticks = TickCount();
  326.                     Yangle += 2;
  327.                     SetGWorld(drawWorldP, nil);
  328.                     PaintRect(&frameRect);
  329.                     rotate ();
  330.                     SetGWorld(saveWorld, saveDevice);
  331.                     while (TickCount() < ticks + 1) {}
  332.                     CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
  333.                         &frameRect, &frameRect, srcCopy, nil);
  334.                     }
  335.                 break;
  336.             }
  337.         break;
  338.     }
  339. }
  340.  
  341. //************************************************************************
  342.  
  343. void finishup (void) /* get outa here */
  344. {
  345.     ExitToShell();
  346. }
  347.  
  348. //************************************************************************
  349.  
  350. void mousepress (Point p)
  351. {
  352.     Point p1;
  353.     int x, y, x1, y1;
  354.     double sx, sy, sz;
  355.     
  356.     /* save original rotation angles */
  357.     sx = Xangle;
  358.     sy = Yangle;
  359.     sz = Zangle;
  360.     
  361.     x1 = 0;
  362.     y1 = 0;
  363.     
  364.     while (StillDown()) /* loop while button held down */
  365.         {
  366.         GetMouse (&p1);
  367.         x = p.v - p1.v;
  368.         y = p.h - p1.h;
  369.         
  370.         if (x != x1 || y != y1) /* if mouse moved since last time around */
  371.             {
  372.             Xangle = sx - x;
  373.             Yangle = sy + y;
  374.             SetGWorld(drawWorldP, nil);
  375.             PaintRect(&frameRect);
  376.             rotate ();
  377.             SetGWorld(saveWorld, saveDevice);
  378.             CopyBits((BitMapPtr)drawPixMapP, (BitMapPtr)windowPixMapP,
  379.                 &frameRect, &frameRect, srcCopy, nil);
  380.             x1 = x;
  381.             y1 = y;
  382.             }
  383.         }
  384. }
  385.  
  386. //************************************************************************
  387.  
  388. void rotate ()
  389. {
  390.     int     Ec;
  391.     double     XV, YV, ZV, X, Y, Z, X3, Y3, Z3;
  392.     double    CB, SB, CH, SH, CP, SP;
  393.     double    AM, BM, CM, DM, EM, FM, GM, HM, IM;
  394.     int        XX, YY;
  395.     double    P, B, H;
  396.  
  397.     P  = PI2 * Xangle / 360 - PI;
  398.     B  = PI2 * Zangle / 360;
  399.     H  = PI2 * Yangle / 360;
  400.     
  401.     CB = cos(B);
  402.     SB = sin(B);
  403.     CH = cos(H);
  404.     SH = sin(H);
  405.     CP = cos(P);
  406.     SP = sin(P);
  407.     
  408.     AM =  CB * CH - SH * SP * SB;
  409.     BM = -CB * SH - SP * CH * SB;
  410.     CM =  CP * SB;
  411.     DM =  SH * CP;
  412.     EM =  CP * CH;
  413.     FM =  SP;
  414.     GM = -CH * SB - SH * SP * CB;
  415.     HM =  SH * SB - SP * CH * CB;
  416.     IM =  CP * CB;
  417.     XV = - DD * CP * SH;
  418.     YV = - DD * CP * CH;
  419.     ZV = - DD * SP;
  420.     for (Ec = 0; Ec < N; Ec++)
  421.         {
  422.         X = aaa[Ec][0] - XV;
  423.         Y = aaa[Ec][1] - YV;
  424.         Z = aaa[Ec][2] - ZV;
  425.         X3 = AM * X + BM * Y + CM * Z;
  426.         Y3 = DM * X + EM * Y + FM * Z;
  427.         Z3 = GM * X + HM * Y + IM * Z;
  428.         XX = round (10 * DD * X3 / Y3 + 200);
  429.         YY = round (10 * DD * Z3 / Y3 + 200);
  430.         if (cc[Ec] != 0)
  431.             {
  432.             /* draw a line */
  433.             RGBForeColor (&white);
  434.             if (abs(cc[Ec]) == 1) RGBForeColor (&red);
  435.             if (abs(cc[Ec]) == 2) RGBForeColor (&green);
  436.             if (abs(cc[Ec]) == 3) RGBForeColor (&blue);
  437.             if (cc[Ec] < 0) MoveTo (XX, YY); /* draw a point */
  438.             LineTo (XX, YY);
  439.             }
  440.         else
  441.             /* move to starting point of line */
  442.             MoveTo (XX, YY);
  443.         }
  444.     RGBForeColor (&black);
  445. }
  446.  
  447. //************************************************************************
  448.  
  449. void getuserfile (void)
  450. {
  451.     SFTypeList types;
  452.     StandardFileReply mySFR;
  453.     
  454.     /* get a file name */
  455.     types[0] = 'TEXT';
  456.     StandardGetFile (NULL, 1, types, &mySFR);
  457.     
  458.     if (mySFR.sfGood)
  459.         {
  460.         readfile (mySFR.sfFile.vRefNum, mySFR.sfFile.parID,
  461.             mySFR.sfFile.name);
  462.         }
  463. }
  464.  
  465. //************************************************************************
  466.  
  467. void    readfile (short refnum, long parid, Str63 name)
  468. {
  469.     FILE *points;
  470.     int    i, j;
  471.     double max, maybe;
  472.         
  473.     SetWTitle ((WindowPtr)thewindow, name);
  474.     
  475.     PtoCstr((StringPtr) name);
  476.     err = HSetVol (NULL, refnum, parid);
  477.     if (err) died ("Could not Set Volume", err, 4);
  478.     
  479.     /* read points from the file */
  480.     points = fopen ((char *)name, "r");
  481.     if (points == NULL) died ("Can't Open File", 0, 5);
  482.     N = 0;
  483.     do
  484.         {
  485.         err = (fscanf(points, "%lf %lf %lf %d", &aaa[N][0], &aaa[N][1],
  486.             &aaa[N][2], &cc[N]));
  487.         if (err != EOF) N++;
  488.         if (err != 4 && err != EOF)
  489.             {
  490.             fclose (points);
  491.             died ("Error Reading File", err, 6);
  492.             }
  493.         if (N > MaxPoints)
  494.             {
  495.             fclose (points);
  496.             died ("Too Many Lines in File", 0, 7);
  497.             }
  498.         }
  499.     while (err != EOF);
  500.     fclose (points);
  501.     
  502.     /* get maximum distance of points from origin */
  503.     max = 0;
  504.     for (i=0; i<N; i++)
  505.         {
  506.         maybe = sqrt(aaa[i][0]*aaa[i][0] + aaa[i][1]*aaa[i][1] +
  507.             aaa[i][2]*aaa[i][2]);
  508.         if (maybe > max) max = maybe;
  509.         }
  510.     if (max == 0) died ("All Points at Origin", 0, 8);
  511.     /* scale the points */
  512.     for (i=0; i<N; i++)
  513.         for (j=0; j<3; j++)
  514.             aaa[i][j] /= max/19;
  515.     
  516.     /* reset rotation angles */
  517.     Xangle = 0;
  518.     Yangle = 0;
  519.     Zangle = 0;
  520.     
  521.     /* draw the picture to GWorld and screen */
  522.     SetGWorld(drawWorldP, nil);
  523.     PaintRect(&frameRect);
  524.     rotate ();
  525.     SetGWorld(saveWorld, saveDevice);
  526.     ShowWindow ((WindowPtr)thewindow);
  527. }
  528.  
  529. //************************************************************************
  530.  
  531. void installAEhandlers (void)
  532. {
  533.     /* install the required apple event handlers */
  534.     AEEventHandlerUPP OPENae, QUITae, STARTae, PRINTae;
  535.     
  536.     /* must use these for PPC proc pointers */
  537.     OPENae = NewAEEventHandlerProc ((ProcPtr) &openAE);
  538.     QUITae = NewAEEventHandlerProc ((ProcPtr) &quitAE);
  539.     STARTae = NewAEEventHandlerProc ((ProcPtr) &startAE);
  540.     PRINTae = NewAEEventHandlerProc ((ProcPtr) &printAE);
  541.     
  542.     err = AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments,
  543.         OPENae, 0, FALSE);
  544.     if (err) died ("Error Installing OpenDoc Apple Event", err, 9);
  545.     
  546.     err = AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
  547.         QUITae, 0, FALSE);
  548.     if (err) died ("Error Installing QuitApp Apple Event", err, 10);
  549.     
  550.     err = AEInstallEventHandler (kCoreEventClass, kAEOpenApplication,
  551.         STARTae, 0, FALSE);
  552.     if (err) died ("Error Installing OpenApp Apple Event", err, 11);
  553.     
  554.     err = AEInstallEventHandler (kCoreEventClass, kAEPrintDocuments,
  555.         PRINTae, 0, FALSE);
  556.     if (err) died ("Error Installing PrintDoc Apple Event", err, 12);
  557. }
  558.  
  559. //************************************************************************
  560.  
  561. void DoHighLevelEvent (EventRecord *theEvent)
  562. {
  563.     /* process high level events */
  564.     err = AEProcessAppleEvent (theEvent);
  565.     if (err) died ("Error Processing Apple Event", err, 13);
  566. }
  567.  
  568. //************************************************************************
  569.  
  570. pascal    OSErr    openAE (AppleEvent *theEvent, AppleEvent *reply, long refcon)
  571. {
  572.     AEDescList    docList;
  573.     long        n;
  574.     AEKeyword    keywd;
  575.     DescType    rtype;
  576.     FSSpec        myFSS;
  577.     Size        acsize;
  578.     
  579.     /* open document apple event */
  580.     err = AEGetParamDesc (theEvent, keyDirectObject, typeAEList, &docList);
  581.     if (err) died ("Error Processing Apple Event", err, 14);
  582.     
  583.     /* count number of document to be opened */
  584.     err = AECountItems (&docList, &n);
  585.     if (err) died ("Error Processing Apple Event", err, 15);
  586.     if (n < 1) died ("No File for OpenDoc Apple Event", 0, 16);
  587.     
  588.     /* get FSS record of the first document only */
  589.     err = AEGetNthPtr (&docList, 1, typeFSS, &keywd, &rtype,
  590.         &myFSS, sizeof(myFSS), &acsize);
  591.     if (err) died ("Error Processing Apple Event", err, 17);
  592.     
  593.     /* get rid of storage */
  594.     err = AEDisposeDesc (&docList);
  595.     if (err) died ("Error Processing Apple Event", err, 18);
  596.     
  597.     /* open the passed file */
  598.     readfile (myFSS.vRefNum, myFSS.parID, myFSS.name);
  599.     
  600.     return noErr;
  601. }
  602.  
  603. //************************************************************************
  604.  
  605. pascal OSErr quitAE(AppleEvent *theEvent, AppleEvent *reply, long refcon)
  606. {
  607.     /* quit apple event - set the done flag */
  608.     done = true;
  609.     return noErr;
  610. }
  611.  
  612. //************************************************************************
  613.  
  614. pascal    OSErr    printAE (AppleEvent *theEvent, AppleEvent *reply, long refcon)
  615. {
  616.     /* print apple event not handled here */
  617.     return errAEEventNotHandled;
  618. }
  619.  
  620. //************************************************************************
  621.  
  622. pascal    OSErr    startAE (AppleEvent *theEvent, AppleEvent *reply, long refcon)
  623. {
  624.     /* startup apple event - ask for an input file */
  625.     getuserfile();
  626.     return noErr;
  627. }
  628.  
  629. //************************************************************************
  630.  
  631. void died (char desc[255], int code, int ref)
  632. {
  633.     /* nasty error has occurred - report it and quit */
  634.     int go;
  635.     char a[50], b[50];
  636.     
  637.     CtoPstr (desc);
  638.     NumToString (code, (StringPtr)a);
  639.     NumToString (ref, (StringPtr)b);
  640.     ParamText ((StringPtr)desc, (StringPtr)a, (StringPtr)b, NULL);
  641.     go = Alert(129,NULL);
  642.     ExitToShell();
  643. }
  644.  
  645. //************************************************************************
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.